using UnityEngine;
using XMLData.Map;
using System.Collections.Generic;

public class LevelGrid : MonoBehaviour {
	
	static LevelGrid instance;
	
	public GameObject[,] world1;
	LayerManager bgLayer1;
	public List<TileObjectPlane> tileObjects1;
	float tileObject1ZPos = -8.1f;
	string bg1Theme;
	
	public MapInfo mapInfo;
	
	public GameObject[,] world2;
	LayerManager bgLayer2;
	public List<TileObjectPlane>tileObjects2;
	float tileObject2ZPos = -4.1f;
	
	GameObject bg;
	GameObject[] sideBoundary;
	
	GridSize _gridSize;
	Vector2 origin = new Vector2(-21, - 8);
	int currentWorldView;
	
	readonly string[] strworld = {"Player1Specific", "Player2Specific"};
	readonly string[] strbg = {"bg1", "bg2"};
	
	int clickableMask;
	Vector2 averagePosition;
	
	int linkedReady1 = 0;
	int linkedReady2 = 0;
	
	void Awake()
	{
		instance = this; 
	}
	
	public void CreateBaseGrid(GridSize _gridSize)
	{
		TileObjectPlane.ResetIDGenerator();
		PrepareCellGrid(_gridSize);
		CreateBG("cute");
		ActivateWorld(1);
	}
	
	/// <summary>
	/// Prepares the cell grid from the pool manager.
	/// </summary>/
	private void PrepareCellGrid(GridSize gridSize)
	{
		destroyGrid();
		_gridSize = gridSize;
		int xLength = _gridSize.X;
		int yLength = _gridSize.Y;
		
		sideBoundary = new GameObject[2];
		world1 = new GameObject[xLength, yLength];
		world2 = new GameObject[xLength, yLength];
		tileObjects1 = new List<TileObjectPlane>();
		tileObjects2 = new List<TileObjectPlane>();
	
		Material mat = LevelAssetManager.Instance.getAsset<Material>(KEYTYPE.MATERIAL, "Wireframe");
		
		int i_world1 = LayerMask.NameToLayer(strworld[0]);
		int i_world2 = LayerMask.NameToLayer(strworld[1]);
		
		GameObject cellObject = LevelAssetManager.Instance.cell;		
		averagePosition = Vector2.zero;
		Vector3 position = Vector3.zero;
		
		for(int y = 0; y < yLength; y++)
		{
			for(int x = 0; x < xLength; x++)
			{
				position = new Vector3(origin.x + 1*x, origin.y + 1 *y, -8);
				GameObject go = Instantiate(cellObject, position, Quaternion.identity) as GameObject;
				go.transform.parent = transform;
				CellGrid cg =  go.AddComponent<CellGrid>();
				cg.gridPosX = x;
				cg.gridPosY = y;
				go.renderer.material = mat;
				go.layer = i_world1;
				world1[x,y] = go;
				
				position.z += 4;
				GameObject go2 = world2[x,y] = Instantiate(cellObject, position, Quaternion.identity) as GameObject;
				go2.transform.parent = transform;
				cg = go2.AddComponent<CellGrid>();
				cg.gridPosX = x;
				cg.gridPosY = y;
				go2.renderer.material = mat;
				go2.layer = i_world2;
				world2[x,y] = go2;
				
				if(y == 1)
					averagePosition.x += position.x;
			}
			averagePosition.y += position.y;
		}
		
		averagePosition.x /= xLength;
		averagePosition.y /= yLength;
	}
	
	void setBoundary(bool isLevelEditor)
	{
		float yZero = 0;
		Vector3 position = Vector3.zero;
		yZero = world1[0,0].transform.position.y;
		position.x = world1[0,0].transform.position.x  - 1;
		position.z = 0;
		position.y = averagePosition.y;
		sideBoundary[0] = Instantiate(LevelAssetManager.Instance.sideBoundary, position, Quaternion.identity) as GameObject;
		
		Vector3 scale = sideBoundary[0].transform.localScale;
		scale.z = 15;
		scale.y = gridSize.Y + 25;
		scale.y *= -1;
		sideBoundary[0].transform.localScale = scale;
		sideBoundary[0].renderer.material = LevelAssetManager.Instance.getAsset<Material>(KEYTYPE.MATERIAL, "LeftCollide");
		sideBoundary[0].renderer.material.mainTextureScale = new Vector2(1, scale.y);
		
		position.x = world1[_gridSize.X - 1,0].transform.position.x  + 1;
		position.z = 0;
		position.y = averagePosition.y;
		sideBoundary[1] = Instantiate(LevelAssetManager.Instance.sideBoundary, position, Quaternion.identity) as GameObject;
		
		scale = sideBoundary[1].transform.localScale;
		scale.z = 15;
		scale.y = gridSize.Y + 25;
		scale.y *= -1;
		sideBoundary[1].transform.localScale = scale;
		sideBoundary[1].renderer.material = LevelAssetManager.Instance.getAsset<Material>(KEYTYPE.MATERIAL, "RightCollide");
		sideBoundary[1].renderer.material.mainTextureScale = new Vector2(1, scale.y);
		
		sideBoundary[0].layer = sideBoundary[1].layer =  0;
		CameraScript mainCam = Camera.main.GetComponent<CameraScript>();
		if(mainCam != null)
		{
			mainCam.leftSide = sideBoundary[0].transform;
			mainCam.rightSide = sideBoundary[1].transform;
		}
		
		if(!isLevelEditor)
		{
			CellGrid rightMostCell = world1[0,0].GetComponent<CellGrid>();
			
			foreach(GameObject go in world1)
			{
				CellGrid cg = go.GetComponent<CellGrid>();
				if(!cg.renderer.enabled)
					continue;
				if(cg.gridPosX > rightMostCell.gridPosX)
				{
					rightMostCell = cg;
				}
			}
			
			foreach(GameObject go in world2)
			{
				CellGrid cg = go.GetComponent<CellGrid>();
				
				if(!cg.renderer.enabled)
					continue;
				
				if(cg.gridPosX > rightMostCell.gridPosX)
				{
					rightMostCell = cg;
				}
			}
			Debug.Log("Right Most Cell is "+ rightMostCell.gridPosX + " : " + rightMostCell.gridPosY);
			position.x = rightMostCell.transform.position.x + 1;
			sideBoundary[1].transform.position = position;
		}
		
		foreach(Transform tf in sideBoundary[0].GetComponentInChildren<Transform>())
		{
			Vector3 _pos = tf.position;
			_pos.y = yZero;
			if(!isLevelEditor)
				_pos.y += 2;	
			tf.transform.position = _pos;
			
			Transform tmpTf = tf.parent;
			tf.transform.parent = null;
			tf.transform.localScale = Vector3.one;
			tf.transform.parent = tmpTf;
			//Vector3 locScale = tf.localScale;
			//locScale.y = 1/(sideBoundary[0].transform.localScale.y);
			//tf.localScale = locScale;
		}
		
		foreach(Transform tf in sideBoundary[1].GetComponentInChildren<Transform>())
		{
			Vector3 _pos = tf.position;
			_pos.y = yZero;
			if(!isLevelEditor)
				_pos.y += 2;
			tf.transform.position = _pos;
			
			Transform tmpTf = tf.parent;
			tf.transform.parent = null;
			tf.transform.localScale = Vector3.one;
			tf.transform.parent = tmpTf;
			
			//Vector3 locScale = tf.localScale;
			//locScale.y = 1/(sideBoundary[1].transform.localScale.y);
			//tf.localScale = locScale;
		}
	}
	
	public TileObjectPlane CreateObject(string image)
	{
		TileObjectPlane tileObjectPlane =  TileObjectPlane.Create(image);
		Vector3 position = tileObjectPlane.transform.position;
		
		switch(currentWorldView)
		{
		case 1:
			tileObjects1.Add(tileObjectPlane);
			position.z = tileObject1ZPos;
			Debug.Log(tileObjectPlane.name + " is added to world1");
			break;
			
		case 2:
			tileObjects2.Add(tileObjectPlane);
			position.z = tileObject2ZPos;
			Debug.Log(tileObjectPlane.name + " is added to world2");
			break;
		}
		tileObjectPlane.transform.position = position;
		return tileObjectPlane;
	}
	
	public void CreateTutorial(string imageName)
	{
		TileObjectPlane top = CreateObject("tut");
		top.tileObject.tutName = imageName;
		top.renderer.material.mainTexture = LevelAssetManager.Instance.getAsset<Texture2D>(KEYTYPE.TUTORIAL, imageName);
	}
	
	public void RemoveFromList(int world, TileObjectPlane tileObjectPlane)
	{
		if(world == 1)
			tileObjects1.Remove(tileObjectPlane);
		
		else if(world == 2)
			tileObjects2.Remove(tileObjectPlane);
	}
	
	public TileObjectPlane FindTilePlane(int id)
	{
		foreach(TileObjectPlane tilePlane in tileObjects1)
		{
			if(tilePlane.ObjectID == id)
			{
				return tilePlane;
			}
		}
		
		foreach(TileObjectPlane tilePlane in tileObjects2)
		{
			if(tilePlane.ObjectID == id)
			{
				return tilePlane;
			}
		}
		return null;
	}
	
	public void LoadAllObjects(MapInfo map, bool isLevelBuilding)
	{
		TileObjectPlane.ResetIDGenerator();
		LoadObjectPerWorld(map, 1, isLevelBuilding);
		LoadObjectPerWorld(map, 2, isLevelBuilding);
		LoadLinks(map.tileObj1);
		LoadLinks(map.tileObj2);
	}
	
	public void LoadAllObjects(MapInfo map, bool isLevelBuilding, int world)
	{
		TileObjectPlane.ResetIDGenerator();
		if(world == 1)
		{
			Debug.Log("Load Object1");
			LoadObjectPerWorld(map, 1, isLevelBuilding);
		}
		
		else if(world == 2)
		{
			Debug.Log("Load Object1");
			LoadObjectPerWorld(map, 2, isLevelBuilding);
		}
	}
	
	[RPC]
	public void LoadAllLinks()
	{
		Debug.Log("Load Links now!!!!");
		LoadLinks(mapInfo.tileObj1);
		LoadLinks(mapInfo.tileObj2);
	}
	
	private void LoadLinks(TileObject[] tileObjects)
	{
		for(int i = 0; i < tileObjects.Length; i++)
		{
			TileObject target = tileObjects[i];
			
			if(!target.isLinked)
				continue;
			
			TileObjectPlane linkablePlane = FindTilePlane(target.ID);
			TileObjectPlane linkedPlane =   FindTilePlane(target.linkedID);
			
			
			if(linkablePlane == null || linkedPlane == null)
			{
				Debug.Log("Linkable: " + target.ID + " Linked With: " + target.linkedID);
				Debug.Log("Linkable Plane is " + linkablePlane + "Linked Plane is " + linkedPlane);
				continue;
			}
			
			TILEOBJECTS targetType = (TILEOBJECTS)target.objectType;
			switch(targetType)
			{
				case TILEOBJECTS.LEVER:
					linkablePlane.GetComponent<leverScript>().partner = linkedPlane.GetComponent<blockScript>();
				break;
				
				case TILEOBJECTS.GROUNDBTN:
					linkablePlane.GetComponent<stepOnButScript>().partner = linkedPlane.GetComponent<platformScript>();
				break;
				
				case TILEOBJECTS.HIDDENPLATFORM:
					hiddenPlatButton _hiddenPlatButton = linkedPlane.GetComponent<hiddenPlatButton>();
					TileObjectPlane tilePlane = _hiddenPlatButton.GetComponent<TileObjectPlane>();
					hiddenPlatformScript _hiddenPlatScript = linkablePlane.GetComponent<hiddenPlatformScript>();
					_hiddenPlatScript.motherButton = _hiddenPlatButton;
					if(!_hiddenPlatButton.platforms.Contains(_hiddenPlatScript))
					{
						_hiddenPlatButton.platforms.Add(_hiddenPlatScript);
						tilePlane.addLink(target.ID, _hiddenPlatScript.transform);
					}
				break;
				
			case TILEOBJECTS.MULTILOCKDOORBTN:
				    MultiLockBWDoor _multiDoor = linkedPlane.GetComponent<MultiLockBWDoor>();
					TileObjectPlane _tilePlane = _multiDoor.GetComponent<TileObjectPlane>();
					MBDButtonScript _mbdButtonScript = linkablePlane.GetComponent<MBDButtonScript>();
					_mbdButtonScript.myDoor = _multiDoor;
					if(!_multiDoor.myButtons.Contains(_mbdButtonScript))
					{
						_multiDoor.addAButton(_mbdButtonScript);
						_tilePlane.addLink(target.ID, _mbdButtonScript.transform);
					}
				break;
			}
		}
	}
	
	private void LoadObjectPerWorld(MapInfo map, int world, bool isLevelBuilding)
	{
		List<TileObjectPlane> targetTileObject = (world == 1)? tileObjects1: tileObjects2;
		int worldMask = LayerMask.NameToLayer((world == 1)? "Player1Specific": "Player2Specific");
		TileObject[] tileObjects = (world ==1)? map.tileObj1: map.tileObj2;
		float zPos = (world == 1)? 3: 0;
		
		for(int i = 0; i < tileObjects.Length; i++)
		{
			if(!isLevelBuilding)
			{
				GameObject go = TileObjectPlane.GetTileObject((TILEOBJECTS)tileObjects[i].objectType);
				
				TileObjectPlane tileObjectPlane = TileObjectPlane.Create(go, tileObjects[i], worldMask);
				targetTileObject.Add(tileObjectPlane);
				
				
				tileObjectPlane.setObjectZPosition(zPos);
				tileObjectPlane.Strip_Add_Components();
				
				networkView.RPC("addTargetTile",RPCMode.Others, 
								tileObjectPlane.networkView.viewID, 
								world, i);
			}
			
			else
			{
				GameObject go = TileObjectPlane.GetTileObjectLevel((TILEOBJECTS)tileObjects[i].objectType);
				TileObjectPlane tileObjectPlane = TileObjectPlane.Create(go, tileObjects[i], worldMask);
				targetTileObject.Add(tileObjectPlane);
			}
		}
		if(!isLevelBuilding)
			networkView.RPC("sendLink", RPCMode.All, world);
	}
	[RPC]
	void sendLink(int readyWorld)
	{
		if(readyWorld == 1)
			linkedReady1 = 1;
		else if(readyWorld == 2)
			linkedReady2 = 1;
		
		if((linkedReady1 == 1) && (linkedReady2 == 1))
		{
			networkView.RPC("LoadAllLinks", RPCMode.All);
		}
	}
	
	[RPC]
	void addTargetTile(NetworkViewID viewID, int world, int index)
	{
		GameObject myObject = NetworkView.Find(viewID).gameObject;
		
		List<TileObjectPlane> targetTileObject = (world == 1)? tileObjects1: tileObjects2;
		int worldMask = LayerMask.NameToLayer((world == 1)? "Player1Specific": "Player2Specific");
		TileObject[] tileObjects = (world ==1)? mapInfo.tileObj1: mapInfo.tileObj2;
		float zPos = (world == 1)? 3: 0;
		
		TileObjectPlane tileObjectPlane = TileObjectPlane.Create(myObject,  tileObjects[index],worldMask);
		targetTileObject.Add(tileObjectPlane);
		
		tileObjectPlane.setObjectZPosition(zPos);
		tileObjectPlane.Strip_Add_Components();
	}
	
	void ObjectsCleanup(int world)
	{
		List<TileObjectPlane> tileObjectPlaneList = (world == 1)? tileObjects1: tileObjects2;
		List<TileObjectPlane> tmpTileObjList = new List<TileObjectPlane>();
		
		foreach(TileObjectPlane go in tileObjectPlaneList)
		{
			if(go != null)
				tmpTileObjList.Add(go);
		}
		
		tileObjectPlaneList = tmpTileObjList;
	}
	public TileObject[] PackageObjectOfWorld(int world)
	{
		ObjectsCleanup(world);
		List<TileObjectPlane> tileObjectPlaneList = (world == 1)? tileObjects1: tileObjects2;
		
		TileObject[] tileObjects = new TileObject[tileObjectPlaneList.Count];
		
		for(int i = 0; i < tileObjects.Length; i++)
		{
			tileObjectPlaneList[i].ReadyExport();
			tileObjects[i] = tileObjectPlaneList[i].Package();
		}
		return tileObjects;
	}

	public BGPlane2D addHighlightToBG(int index)
	{
		for(int i = 0; i < bgLayer2.LayerCount - 1; i++)
		{
			if(i == index)
				continue;
			getBGPlane(i).SetColor(new Color(0.05f, 0.05f,0.05f, 1.0f));
		}
		return getBGPlane(index);
	}
	
	public void returnBGPlaneColor()
	{
		if(bgLayer2 == null)
			return;
		for(int i = 0; i < bgLayer2.LayerCount - 1; i++)
		{
			getBGPlane(i).SetColor(Color.white);
		}
	}
	public BGPlane2D AddBackground(Texture2D image)
	{
		Vector3 position = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 1));
		LayerManager layerManager = (currentWorldView ==1)? bgLayer1: bgLayer2;
		Layer2D layer = layerManager.getLayer(layerManager.LayerCount -1);
		BGPlane2D bgPlane = new BGPlane2D("CustomBG", layer, new Vector2(position.x, position.y),true);
		bgPlane.SetScale(new Vector2(2,2));
		bgPlane.SetImage(KEYTYPE.BG, image);
		bgPlane.ResetScaleAndPosition();
		ReferencePlane2D rp2D = bgPlane.AddComponent<ReferencePlane2D>();
		rp2D.attachedPlane2D = bgPlane;
		bgPlane.AddComponent<BoxCollider>();
		layer.AddPlane2D(bgPlane);
	 	return null;	
	}
	
	public void CreateBG(string keyWord)
	{
		GameObject go = null;
		if(bg != null)
			Destroy(bg);
		
		bg1Theme = keyWord;
		
		if(keyWord.ToLower().Contains("cute"))
		{
			GameObject _go = LevelAssetManager.Instance.getAsset<GameObject>(KEYTYPE.PREFAB, "CuteBG");
			bg = go = MonoBehaviour.Instantiate(_go) as GameObject;
		}
		go.transform.parent = Camera.main.transform;
		go.transform.localPosition = Vector3.zero;
		
		
		BGManager bgCam = Camera.main.GetComponent<BGManager>();
		bgCam.enabled = true;
		bgCam.backgrounds = new Transform[3];
		staticTools.SetLayerRecursively(bg, 0);
		int count = 0;
		foreach(Transform _transform in go.GetComponentInChildren<Transform>())
		{
			try
			{
			bgCam.backgrounds[count] = _transform;
			count++;
			if(count > 3)
				break;
			}
			catch{}
		}
	}
	private void CreateBG()
	{
		bgLayer1 = new LayerManager(-6,LayerMask.NameToLayer(strbg[0]));
		bgLayer2 = new LayerManager(-1,LayerMask.NameToLayer(strbg[1]));
		
		LevelAssetManager lam = LevelAssetManager.Instance;
		Texture2D[] images = lam.getAssets<Texture2D>(KEYTYPE.PARALLAX, "CAVE");
		Texture2D[] images1 = lam.getAssets<Texture2D>(KEYTYPE.PARALLAX, "CITY");
		
		for(int i = 0; i< 3;i++)
		{
			Layer2D subLayer1 = bgLayer1.CreateLayer();
			BGPlane2D newPlane = new BGPlane2D("BG" + i, subLayer1, averagePosition);
			newPlane.SetScale(new Vector2(_gridSize.X, _gridSize.Y));
			newPlane.ResetScaleAndPosition();
			newPlane.SetImage(KEYTYPE.PARALLAX, images[i]);
			subLayer1.AddPlane2D(newPlane); 
			
			Layer2D subLayer2 = bgLayer2.CreateLayer();
			newPlane = new BGPlane2D("BG" + i, subLayer2, averagePosition);
			newPlane.SetScale(new Vector2(_gridSize.X, _gridSize.Y));
			newPlane.ResetScaleAndPosition();
			newPlane.SetImage(KEYTYPE.PARALLAX, images1[i]);
			subLayer2.AddPlane2D(newPlane); 
		}
		
		//Last layer
		bgLayer1.CreateLayer();
		bgLayer2.CreateLayer();
	}
	
	public void changeBackground(string theme)
	{
		LayerManager layerManager = (currentWorldView == 1)? bgLayer1: bgLayer2;
		LevelAssetManager lam = LevelAssetManager.Instance;
		Texture2D[] images = lam.getAssets<Texture2D>(KEYTYPE.PARALLAX, theme.ToUpper());
		for(int i = 0; i < 3; i++)
		{
			Layer2D subLayer = layerManager.getLayer(i);
			Plane2D plane =  subLayer.GetPlane(0);
			plane.SetImage(KEYTYPE.PARALLAX, images[i]);
		}
	}
	
	public void LoadBGPackage(XMLData.Map.MapInfo mapInfo)
	{
		this.CreateBG(mapInfo.bg1);
		Camera.main.cullingMask |= 1 << LayerMask.NameToLayer("Default");
	}
	
	private void LoadBGPerWorld(LayerManager layerManager, LayerManagerInfo layerManagerInfo)
	{
		for(int i =0; i < layerManagerInfo.layers.Length -1; i++)
		{
			Layer2D layer2D = layerManager.CreateLayer();
			Layer2DInfo layer2DInfo = layerManagerInfo.layers[i];
			Plane2DInfo plane2DInfo = layer2DInfo.plane2DList[0];
			Vector2 position = new Vector2(plane2DInfo.position.x, plane2DInfo.position.y);
			BGPlane2D plane2D = new BGPlane2D(plane2DInfo.planeName, layer2D, position);
			Vector2 scale = new Vector2(plane2DInfo.scale.x, plane2DInfo.scale.y);
			layer2D.AddPlane2D(plane2D);
			plane2D.SetScale(scale);
			plane2D.SetMaterial(plane2DInfo.planeMaterial);
			plane2D.ResetScaleAndPosition();
		}
		
		Layer2D _layer2D = layerManager.CreateLayer();
		Layer2DInfo _layer2DInfo = layerManagerInfo.layers[layerManagerInfo.layers.Length -1]; 
		for(int k = 0; k < _layer2DInfo.plane2DList.Length; k++)
		{
			Plane2DInfo plane2DInfo = _layer2DInfo.plane2DList[k];
			Vector2 position = new Vector2(plane2DInfo.position.x, plane2DInfo.position.y);
			BGPlane2D plane2D = new BGPlane2D(plane2DInfo.planeName, _layer2D, position, true);
			Vector2 scale = new Vector2(plane2DInfo.scale.x, plane2DInfo.scale.y);
			_layer2D.AddPlane2D(plane2D);
			plane2D.SetScale(scale);
			
			plane2D.SetMaterial(plane2DInfo.planeMaterial);
			plane2D.ResetScaleAndPosition();
			ReferencePlane2D rp2D = plane2D.AddComponent<ReferencePlane2D>();
			rp2D.attachedPlane2D = plane2D;
			plane2D.AddComponent<BoxCollider>();
		}
	}
	
	public void destroyGrid()
	{
		//Check if cell array has something
		if(world1 != null)
		{
			foreach(GameObject go in world1)
				Destroy(go);
		}
		
		if(world2 != null)
		{
			foreach(GameObject go in world2)
				Destroy(go);
		}
		
		if(sideBoundary != null)
		{
			foreach(GameObject go in sideBoundary)
				Destroy(go);
		}
		
		if(bg != null)
			Destroy(bg);
		
		if(bgLayer1 != null)
			bgLayer1.Destroy();
		
		if(bgLayer2 != null)
			bgLayer2.Destroy();
		
		if(tileObjects1 != null)
		{
			foreach(TileObjectPlane go in tileObjects1)
				Destroy(go.gameObject);
			tileObjects1.Clear();
		}
		
		if(tileObjects2 != null)
		{
			foreach(TileObjectPlane go in tileObjects2)
				Destroy(go.gameObject);
			tileObjects2.Clear();
		}
	}
	
	public void ActivateCellCollider(bool isActivate)
	{
		
		//Check if cell array has something
		if(world1 != null)
		{
			foreach(GameObject go in world1)
			{
				go.collider.enabled = isActivate;
			}
		}
		
		if(world2 != null)
		{
			foreach(GameObject go in world2)
			{
				go.collider.enabled = isActivate;
			}
		}
	}
	
	public void ActivateObjectCollider(bool isActivate)
	{
		List<int> obj1 = new List<int>();
		List<int> obj2 = new List<int>();
		int count = 0;
		
		ObjectsCleanup(1);
		ObjectsCleanup(2);
		
		if(tileObjects1 != null)
		{
			foreach(TileObjectPlane go in tileObjects1)
			{
				try
				{
					go.collider.enabled = isActivate;
				}catch{obj1.Add(count);}
				count++;
			}
		}
		
		count = 0;
		if(tileObjects2 != null)
		{
			foreach(TileObjectPlane go in tileObjects2)
			{
				try
				{
					go.collider.enabled = isActivate;
				}catch{obj2.Add(count);}
				count++;
			}
		}
		
		foreach(int i  in obj1)
			tileObjects1.RemoveAt(i);
		
		foreach(int i in obj2)
			tileObjects2.RemoveAt(i);
	}
	/// <summary>
	/// Loads the cell grid from the XML.
	/// </summary>
	/// <param name='cellGroup'>
	/// Cell group from XML file
	/// <param name='isLevelBuilding'>
	/// Is this on level building mode?
	/// </param>
	public void loadCellGrid(MapInfo cellGroup, bool isLevelBuilding)
	{
		if(cellGroup == null)
			return;
		
		PrepareCellGrid(new GridSize(cellGroup.lengthX, cellGroup.lengthY));
		
		LevelAssetManager   cm = LevelAssetManager.Instance;
		Material material = cm.getAsset<Material>(KEYTYPE.MATERIAL, "CellMat");
		Material gridMat =  cm.getAsset<Material>(KEYTYPE.MATERIAL, "Wireframe");
		
		foreach(ICell ci in cellGroup.world1)
		{
			GameObject go = world1[ci.gX, ci.gY];
			go.renderer.enabled = ci.iSee;
			go.transform.position = new Vector3(ci.x, ci.y, ci.z);
			go.name = ci.n;
			
			if(ci.iSee)
			{
				Texture2D image = cm.getAsset<Texture2D>(KEYTYPE.CELL, go.name);
				go.GetComponent<CellGrid>().setHasTexture(image, material);
			}
			else
			{
				go.renderer.enabled = isLevelBuilding;
				go.renderer.material = gridMat;
			}
			
			if(!isLevelBuilding)
			{
				CellGrid cg = go.GetComponent<CellGrid>();
				Vector3 position = go.transform.position;
				position.z  = 3;
				go.transform.position = position;
				if(cg == null)
					continue;
				cg.Strip_Add_Components();
			}
		}
		
		foreach(ICell ci in cellGroup.world2)
		{
			GameObject go = world2[ci.gX, ci.gY];
			go.renderer.enabled = ci.iSee;
			go.transform.position = new Vector3(ci.x, ci.y, ci.z);
			go.name = ci.n;
			
			if(ci.iSee)
			{
				Texture2D image = cm.getAsset<Texture2D>(KEYTYPE.CELL, go.name);
				go.GetComponent<CellGrid>().setHasTexture( image, material);
			}
			
			else
			{
				go.renderer.enabled = isLevelBuilding;
				go.renderer.material = gridMat;
			}
			
			if(!isLevelBuilding)
			{
				CellGrid cg = go.GetComponent<CellGrid>();
				Vector3 position = go.transform.position;
				position.z  = 0;
				go.transform.position = position;
				if(cg == null)
					continue;
				cg.Strip_Add_Components();
			}
			
		}
		
		EditorCamera editorCam = Camera.main.GetComponent<EditorCamera>();
		if(editorCam != null)
			editorCam.SetMinMaxViewPos(new GridSize(cellGroup.lengthX, cellGroup.lengthY));
		setBoundary(isLevelBuilding);
	}
	
	
	/// <summary>
	/// Hides and Show the current BG based on the current world view
	/// without deactivating the world view
	/// </summary>
	public void ReprocessBG()
	{
		switch(currentWorldView)
		{
			case 1:
    		Camera.main.cullingMask |=   1 << LayerMask.NameToLayer(strbg[0]);
			Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strbg[1]));
			break;
			
			case 2:
			Camera.main.cullingMask |= 1 << LayerMask.NameToLayer(strbg[1]);
			Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strbg[0]));
			break;
		}
		computeClickableMask();
	}
	
	
	/// <summary>
	/// The same as the capability of reprocess background but with 
	/// added feature of deactivating world view
	/// </summary>
	public void BGEdit()
	{
		DeactivateWorldView();
		ReprocessBG();
	}
	
	void computeClickableMask()
	{
		var layerMask = 1 << LayerMask.NameToLayer(strworld[1]);
	    layerMask |= 1 << LayerMask.NameToLayer(strworld[0]);
		layerMask|= 1 << LayerMask.NameToLayer("Ignore Raycast");
		
		if(currentWorldView == 1)
	    	layerMask |= 1 << LayerMask.NameToLayer(strbg[1]);
		else
			layerMask |= 1 << LayerMask.NameToLayer(strbg[0]);
		
	    layerMask = ~layerMask;
		
		clickableMask = layerMask;
	}
	
	public void DeactivateWorldView()
	{
		Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strworld[1]));
		Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strworld[0]));
	}
	
	public void ActivateWorld(int world)
	{
		Show(world);
	}
	
	public void ActivateWorld()
	{
		Show(currentWorldView);
	}
	
	public BGPlane2D getBGPlane(int layerIndex)
	{
		Layer2D layer2d = null;
		switch(currentWorldView)
		{
		case 1:
			layer2d = bgLayer1.getLayer(layerIndex);
			break;
			
		case 2:
			layer2d = bgLayer2.getLayer(layerIndex);
			break;
		}
		return (BGPlane2D)layer2d.GetPlane(0);
	}
	
	private void Show(int world) 
	{
		currentWorldView = world;
		switch(world)
		{
			case 1:
    		Camera.main.cullingMask |=   1 << LayerMask.NameToLayer(strworld[0]);
			Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strworld[1]));
			break;
			
			case 2:
			Camera.main.cullingMask |= 1 << LayerMask.NameToLayer(strworld[1]);
			Camera.main.cullingMask &=  ~(1 << LayerMask.NameToLayer(strworld[0]));
			break;
		}
		ReprocessBG();
	}
	
	#region GETTERS
	public GameObject[,] World1
	{
		get{return world1;}
	}
	
	public GameObject[,] World2
	{
		get{return world2;}
	}
	
	public LayerManager BG1
	{
		get{return bgLayer1;}
	}
	
	public LayerManager BG2
	{
		get{return bgLayer2;}
	}
	
	public int CurrentWorldMask
	{
		get{ return (currentWorldView == 1)? LayerMask.NameToLayer(strworld[0]) : LayerMask.NameToLayer(strworld[1]);}
	}
	
	public int CurrentWorldViewIndex
	{
		get{return currentWorldView;}
	}
	
	public GridSize gridSize
	{
		get{return _gridSize;}
	}
	
	public LayerMask ClickableMask
	{
		get{
			return clickableMask;}
	}
	
	public string BG1Theme
	{
		get{return bg1Theme;}	
	}
	
	public static LevelGrid Instance
	{
		get{return instance;}
	}
	#endregion
}
